﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Web.Routing;

namespace MvcControlToolkit
{
    public static class AjaxHelperExtensions
    {
        public static IEnumerable<JsonConverter> CommonConverters
        {
            get
            {
                yield return new JavaScriptDateTimeConverter();
                yield return new JavaScriptElementReferenceConverter();
                yield return new JavaScriptRouteValueDictionaryConverter();
            }
        }

        public static string MicrosoftAjaxInclude(this AjaxHelper helper)
        {
            return helper.MicrosoftAjaxInclude("MicrosoftAjax.js");
        }

        public static string MicrosoftAjaxInclude(this AjaxHelper helper, string scriptName)
        {
            return ScriptInclude(helper, Config.MS_AJAX_DIR + scriptName);
        }

        public static string ToolkitInclude(this AjaxHelper helper, params string[] fileNames)
        {
            string fullUrl;
            var sb = new StringBuilder();

            foreach (string item in fileNames)
            {
                fullUrl = Config.ACT_VIRTUAL_PATH + item;
                sb.Append(helper.ScriptInclude(fullUrl));
            }

            return sb.ToString();
        }


        public static string DynamicToolkitCssInclude(this AjaxHelper helper, string fileName)
        {
            var fullUrl = Config.ACT_VIRTUAL_PATH + fileName;
            return helper.DynamicCssInclude(fullUrl);
        }

        public static string DynamicCssInclude(this AjaxHelper helper, string url)
        {
            //only include if it hasn't been done yet            
            var tracker = new ResourceTracker(helper.ViewContext.HttpContext);
            if (!tracker.Contains(url))
            {
                //build include script
                var sb = new StringBuilder();
                sb.Append("<script type=\"text/javascript\" language=\"javascript\">");
                sb.Append("(function() {");
                sb.Append("var link=document.createElement('link');");
                sb.Append("link.setAttribute('rel', 'stylesheet');");
                sb.Append("link.setAttribute('type', 'text/css');");
                sb.AppendFormat("link.setAttribute('href', '{0}');", url);
                sb.Append("var head = document.getElementsByTagName('head')[0];");
                sb.Append("head.appendChild(link);");
                sb.Append("})();");
                sb.Append("</script>");

                //add to tracker
                tracker.Add(url);

                //return include script
                return sb.ToString();
            }

            //already included
            return string.Empty;
        }

        public static string ScriptInclude(this AjaxHelper helper, params string[] url)
        {
            //get a resource tracker for this request context
            var tracker = new ResourceTracker(helper.ViewContext.HttpContext);

            //add includes if needed
            var sb = new StringBuilder();
            foreach (var item in url)
            {
                if (!tracker.Contains(item))
                {
                    tracker.Add(item);
                    sb.AppendFormat(Config.SCRIPT_INCLUDE_FORMAT, item);
                }
            }

            return sb.ToString();
        }

        public static string Create(this AjaxHelper helper, string clientType, string elementId)
        {
            return helper.Create(clientType, "null", elementId);
        }

        public static string Create(this AjaxHelper helper, string clientType, object properties, string elementId)
        {
            string jsonProperties = "null";

            RouteValueDictionary props = new RouteValueDictionary();

            //serialize properties
            if (properties != null)
            {
                if (properties is IDictionary<string, object>)
                {
                    props = new RouteValueDictionary();
                    props.AddRange(properties as IDictionary<string, object>);
                }
                else
                    props = new RouteValueDictionary(properties);
            }

            //add id
            props.AddIfUnique("id", string.Format("{0}_javascript_id", elementId));

            //serialize properties
            jsonProperties = JavaScriptConvert.SerializeObject(props, CommonConverters.ToArray());

            //build create script
            var sb = new StringBuilder();
            sb.Append("<script type=\"text/javascript\" language=\"javascript\">");
            sb.Append("(function() {");
            sb.Append("Sys.Application.add_init(function() {");
            sb.AppendFormat("$create({0},{1},null,null,$get('{2}'))", clientType, jsonProperties, elementId);
            sb.Append("});");
            sb.Append("})();");
            sb.Append("</script>");

            return sb.ToString();
        }
    }
}
